/*
 * queue.c
 *
 *  Created on: May 3, 2011
 *      Author: tvale, dmourao
 */
#include "queue.h"
#include "common.h"
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>

/*
 * A node in the queue.
 * Contains an element and pointer to the next node in the queue,
 * in a singly-linked list fashion.
 */
typedef struct node {
  msg_t        elem;
  struct node* next;
} node_t;

/*
 * The queue implementation.
 * A singly-linked list of nodes, and a state.
 */
typedef struct queue {
  node_t* head;
  node_t* tail;
  int     state;
} queue_t;


/*
 * Operations.
 */
static void
queue_init(queue_t* queue)
{
  queue->head   = NULL;
  queue->tail   = NULL;
  queue->state  = QUEUE_EMPTY;
}

queue_t*
queue_create()
{
  queue_t* queue = (queue_t*) malloc(sizeof(queue_t));
  queue_init(queue);
  return queue;
}

void
queue_destroy(queue_t* queue)
{
  while (queue->head != NULL) {
    node_t* node = queue->head;
    queue->head  = queue->head->next;
    free(node);
  }

  free(queue);
}

msg_t
queue_remove(queue_t* queue)
{
  node_t* old_head = queue->head;
  msg_t   res      = old_head->elem;

  queue->head = old_head->next;

  if (queue->head == NULL) {
    queue->tail  = NULL;
    queue->state = QUEUE_EMPTY;
  }

  free(old_head);

  return res;
}

msg_t*
queue_peek(queue_t* queue)
{
  return &(queue->head->elem);
}

void
queue_add(queue_t* queue, msg_t elem)
{
  node_t* node = (node_t*) malloc(sizeof(node_t));
  
  node->elem   = elem;
  node->next   = NULL;

  if (queue->head == NULL) {
    queue->head = node;
  } else {
    queue->tail->next = node;
  }

  queue->tail  = node;
  if (queue->state != QUEUE_FINISHED)
    queue->state = QUEUE_NOT_EMPTY;
}

void
queue_set_state(queue_t* queue, queue_state_t state)
{
  queue->state = state;
}

queue_state_t
queue_get_state(queue_t* queue)
{
  return queue->state;
}

void
queue_print(queue_t* queue, FILE* f)
{
  node_t* ptr = queue->head;
  fprintf(f, "[ ");

  while (ptr != NULL) {
    fprintf(f, "%i ", ptr->elem.type);
    ptr = ptr->next;
  }

  fprintf(f, "]");
}
